interface StoreData {
  id: string | number;
  [key: string]: any;
}

class IndexedDB {
  private dbName: string;
  private version: number;
  private db: IDBDatabase | null;

  constructor(dbName: string, version: number = 7) {
    this.dbName = dbName;
    this.version = version;
    this.db = null;
  }

  // 初始化数据库
  init(): Promise<IDBDatabase> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.version);
      request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
        const db = (event.target as IDBRequest).result as IDBDatabase;
        if (!db.objectStoreNames.contains("singleChat")) {
          db.createObjectStore("singleChat", { keyPath: "id" });
        }
        if (!db.objectStoreNames.contains("friendList")) {
          db.createObjectStore("friendList", { keyPath: "id" });
        }
        if (!db.objectStoreNames.contains("groupChat")) {
          db.createObjectStore("groupChat", { keyPath: "id" });
        }
        if (!db.objectStoreNames.contains("chatList")) {
          db.createObjectStore("chatList", { keyPath: "id" });
        }
        if (!db.objectStoreNames.contains("unreadMessage")) {
          db.createObjectStore("unreadMessage", { keyPath: "id" });
        }
      };

      request.onsuccess = (event: Event) => {
        this.db = (event.target as IDBRequest).result as IDBDatabase;
        resolve(this.db);
      };

      request.onerror = (event: Event) => {
        reject({ message: "数据库打开失败", event });
      };
    });
  }

  // 通用保存和覆盖原有数据方法
  saveData(storeName: string, data: StoreData[]): Promise<string> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([storeName], "readwrite");
      const store = transaction.objectStore(storeName);

      const savePromises = data.map((item) => {
        // 确保数据保存时附加当前用户 ID
        item.myUserId = myUserId;

        // 判断是否是对象或数组，如果是则转为 JSON 字符串
        for (const key in item) {
          if (item.hasOwnProperty(key)) {
            const value = item[key];
            if (typeof value === "object" || Array.isArray(value)) {
              // 将对象或数组转为 JSON 字符串
              item[key] = JSON.stringify(value);
            }
          }
        }

        return new Promise<void>((res, rej) => {
          const request = store.put(item);
          request.onsuccess = () => res();
          request.onerror = () => rej(`保存数据到 ${storeName} 失败`);
        });
      });

      Promise.all(savePromises)
        .then(() => resolve(`数据保存成功到 ${storeName}`))
        .catch(reject);
    });
  }

  // 更新数据
  updateData(
    storeName: string,
    filters: Partial<StoreData>,
    updates: Partial<StoreData>
  ): Promise<string> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([storeName], "readwrite");
      const store = transaction.objectStore(storeName);
      const request = store.openCursor();

      const updatedKeys: any[] = [];

      request.onsuccess = (event: Event) => {
        const cursor = (event.target as IDBRequest)
          .result as IDBCursorWithValue;

        if (cursor) {
          const item = cursor.value;

          const match = Object.keys(filters).every(
            (key) => item[key] === filters[key]
          );

          if (match && item.myUserId === myUserId) {
            // 只更新当前用户的数据
            const updatedItem = { ...item, ...updates };

            // 对更新字段进行处理，判断是否是对象或数组，如果是则转为 JSON 字符串
            for (const key in updatedItem) {
              if (updatedItem.hasOwnProperty(key)) {
                const value = updatedItem[key];
                if (typeof value === "object" || Array.isArray(value)) {
                  updatedItem[key] = JSON.stringify(value); // 将对象或数组转为 JSON 字符串
                }
              }
            }

            cursor.update(updatedItem);
            updatedKeys.push(cursor.key);
          }

          cursor.continue();
        } else {
          if (updatedKeys.length > 0) {
            resolve(`成功更新 ${updatedKeys.length} 条记录`);
          } else {
            resolve("没有符合条件的数据需要更新");
          }
        }
      };

      request.onerror = () => reject("更新数据失败");
    });
  }

  // 删除数据
  async deleteData(storeName: string, delData: StoreData): Promise<string> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([storeName], "readwrite");
      const store = transaction.objectStore(storeName);

      const request = store.openCursor();
      let deleteCount = 0;

      request.onsuccess = (event: Event) => {
        const cursor = (event.target as IDBRequest)
          .result as IDBCursorWithValue;
        if (cursor) {
          const match = Object.keys(delData).every(
            (key) => cursor.value[key] === delData[key]
          );

          if (match && cursor.value.myUserId === myUserId) {
            // 只删除当前用户的数据
            const deleteRequest = cursor.delete();
            deleteRequest.onsuccess = () => {
              deleteCount++;
            };
          }

          cursor.continue();
        } else {
          resolve(`成功删除 ${deleteCount} 条数据`);
        }
      };

      request.onerror = () => {
        reject("数据删除失败");
      };
    });
  }

  // 批量删除数据
  async deleteMultiple(
    storeName: string,
    delDatas: StoreData[]
  ): Promise<string> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise(async (resolve, reject) => {
      const deletePromises = delDatas.map((item) => {
        item.myUserId = myUserId; // 传入当前用户 ID
        return this.deleteData(storeName, item);
      });

      Promise.all(deletePromises)
        .then(() => resolve("批量删除成功"))
        .catch(reject);
    });
  }

  // 查询单条详细信息
  getDataDetails(
    storeName: string,
    filters: StoreData = { id: 0 }
  ): Promise<StoreData | null> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([storeName], "readonly");
      const store = transaction.objectStore(storeName);
      const request = store.openCursor();

      request.onsuccess = (event: Event) => {
        const cursor = (event.target as IDBRequest)
          .result as IDBCursorWithValue;
        if (cursor) {
          const match = Object.keys(filters).every(
            (key) => cursor.value[key] === filters[key]
          );
          if (match && cursor.value.myUserId === myUserId) {
            // 只返回当前用户的数据
            resolve(cursor.value);
          } else {
            cursor.continue();
          }
        } else {
          resolve(null);
        }
      };

      request.onerror = () => {
        reject("加载详细信息失败");
      };
    });
  }

  // 通用加载方法
  loadData(storeName: string, setDatasql: any): Promise<StoreData[]> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise((resolve, reject) => {
      const {
        page = 1,
        limit = Infinity,
        sortField = "Time",
        sortOrder = "desc",
        ...filters
      } = setDatasql || {};

      // 创建一个存储查询条件的数组
      const whereConditions: Array<(item: StoreData) => boolean> = [];

      // 处理不等于条件 (例如：Cmd: { $ne: 7 })
      Object.entries(filters).forEach(([key, value]: any) => {
        if (value && value.$ne !== undefined) {
          // 如果条件是 $ne, 添加 "不等于" 的过滤
          whereConditions.push((item) => item[key] !== value.$ne);
          delete filters[key]; // 删除已经处理过的字段
        }
      });

      // 处理其他的普通条件 (例如：chatId: userId)
      Object.entries(filters).forEach(([key, value]) => {
        whereConditions.push((item) => item[key] === value);
      });

      // 在 `IndexedDB` 中进行查询
      const transaction = this.db!.transaction([storeName], "readonly");
      const store = transaction.objectStore(storeName);
      const items: StoreData[] = [];
      const request = store.openCursor();

      request.onsuccess = (event: Event) => {
        const cursor = (event.target as IDBRequest)
          .result as IDBCursorWithValue;

        if (cursor) {
          const item = cursor.value;
          let match = true;

          // 使用 whereConditions 数组中的过滤函数进行匹配
          for (const condition of whereConditions) {
            if (!condition(item)) {
              match = false;
              break;
            }
          }

          // 过滤通过当前用户ID匹配的数据
          if (match && item.myUserId === myUserId) {
            // 对每个字段进行解析，如果是JSON字符串则解析为对象或数组
            for (const key in item) {
              if (item.hasOwnProperty(key)) {
                const value = item[key];
                // 判断是否是JSON字符串，如果是则解析
                if (
                  typeof value === "string" &&
                  (value.startsWith("{") || value.startsWith("["))
                ) {
                  try {
                    item[key] = JSON.parse(value); // 解析为对象或数组
                  } catch (e) {
                    // 如果 JSON 解析失败，不做任何更改
                    console.error(`JSON 解析失败: ${key} = ${value}`);
                  }
                }
              }
            }
            items.push(item);
          }
          cursor.continue();
        } else {
          // 排序处理
          if (sortField) {
            items.sort((a, b) => {
              if (a[sortField] < b[sortField])
                return sortOrder === "asc" ? -1 : 1;
              if (a[sortField] > b[sortField])
                return sortOrder === "asc" ? 1 : -1;
              return 0;
            });
          }
          const filteredItems = items.slice((page - 1) * limit, page * limit);
          resolve(filteredItems);
        }
      };

      request.onerror = () => reject("加载数据失败");
    });
  }

  // 查询对象存储空间中的数据总条数
  countData(
    storeName: string,
    conditions: StoreData = { id: "" }
  ): Promise<number> {
    let myUserInfo = uni.getStorageSync("userInfo");
    let myUserId = myUserInfo.user_id;

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([storeName], "readonly");
      const store = transaction.objectStore(storeName);

      let count = 0;
      const request = store.openCursor();

      request.onsuccess = (event: Event) => {
        const cursor = (event.target as IDBRequest)
          .result as IDBCursorWithValue;
        if (cursor) {
          const match = Object.keys(conditions).every(
            (key) => cursor.value[key] === conditions[key]
          );
          if (cursor.value.myUserId === myUserId && match) {
            // 只统计当前用户的数据
            count++;
          }
          cursor.continue();
        } else {
          resolve(count);
        }
      };

      request.onerror = () => reject("查询数据条数失败");
    });
  }

  // 备份数据库
  backupDatabase(): Promise<string> {
    return new Promise((resolve, reject) => {
      const data: { [key: string]: any[] } = {}; // 使用索引类型定义为字符串键，值为数组
      const transaction = this.db!.transaction(
        this.db!.objectStoreNames as unknown as string[],
        "readonly"
      );

      let storeCount = 0;
      const totalStores = this.db!.objectStoreNames.length;

      // 使用 Array.from() 将 DOMStringList 转换为 string[] 数组
      for (let storeName of Array.from(this.db!.objectStoreNames)) {
        const store = transaction.objectStore(storeName);
        const items: any[] = []; // 数据存储数组

        const request = store.openCursor();
        request.onsuccess = (event: Event) => {
          const cursor = (event.target as IDBRequest)
            .result as IDBCursorWithValue;
          if (cursor) {
            items.push(cursor.value);
            cursor.continue();
          } else {
            // 存储当前对象存储空间的数据
            data[storeName] = items;
            storeCount++;

            // 如果所有存储空间都已处理，完成备份
            if (storeCount === totalStores) {
              const jsonData = JSON.stringify(data, null, 2);
              // 触发下载文件
              this.downloadFile("backup.json", jsonData);
              resolve("备份成功");
            }
          }
        };

        request.onerror = () => {
          reject(`读取 ${storeName} 数据失败`);
        };
      }
    });
  }

  // 下载文件的辅助函数
  downloadFile(filename: string, data: string): void {
    const blob = new Blob([data], {
      type: "application/json",
    });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }

  // 还原数据
  restoreFromFile(jsonData: string): Promise<string> {
    const data: { [key: string]: any[] } = JSON.parse(jsonData);
    const promises: Promise<string>[] = []; // 将 Promise<void> 改为 Promise<string>

    for (const storeName in data) {
      promises.push(this.saveData(storeName, data[storeName])); // 假设 saveData 返回的是 Promise<string>
    }

    return Promise.all(promises)
      .then(() => "还原成功") // 最终返回一个 string
      .catch((err: Error) => {
        throw new Error("还原失败: " + err.message);
      });
  }
}

export default IndexedDB;
